﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UMC.Data;
using UMC.Host;
using UMC.Net;
using UMC.Proxy.Entities;
using UMC.Web;

namespace UMC.Proxy
{

    public class HttpMimeServier : IDoWorker
    {
        static String _Server = Dns.GetHostName();
        public static String Server => _Server;

        X509Certificate certificate;
        X509Certificate ServerCertificateSelectionCallback(object sender, string hostName)
        {
            if (String.IsNullOrEmpty(hostName) == false)
            {
                if (Certificater.Certificates.TryGetValue(hostName, out var x509Certificate))
                {
                    return x509Certificate.Certificate ?? certificate;
                }
                else
                {
                    var l = hostName.IndexOf('.');
                    if (l > 0)
                    {
                        var cName = "*" + hostName.Substring(l);
                        if (Certificater.Certificates.TryGetValue(cName, out var x509))
                        {
                            return x509.Certificate ?? certificate;
                        }
                        else
                        {
                            var certs = HotCache.Find(new SiteCert { Domain = hostName }, "Domain", new string[] { cName });
                            if (certs?.Length > 0)
                            {
                                var cert = certs[0];

                                if (String.IsNullOrEmpty(cert.PrivateKey) && certs.Length > 1)
                                {
                                    cert = certs[1];
                                }
                                if (String.IsNullOrEmpty(cert.PrivateKey) == false && String.IsNullOrEmpty(cert.PublicKey) == false)
                                {
                                    try
                                    {
                                        var x5092 = X509Certificate2.CreateFromPem(cert.PublicKey, cert.PrivateKey);
                                        Certificater.Certificates[cert.Domain] = new Certificater
                                        {
                                            Name = cert.Domain,
                                            Certificate = x5092
                                        };
                                        return x5092;
                                    }
                                    catch
                                    {
                                    }
                                }
                            }
                            else
                            {
                                SignSSL(hostName);
                            }
                        }
                    }
                }
            }
            return certificate;
        }

        SslServerAuthenticationOptions sslServerAuthentication;
        Dictionary<int, Socket[]> _host = new Dictionary<int, Socket[]>();

        Socket BindSocket(IPEndPoint point, EventHandler<SocketAsyncEventArgs> Completed)
        {
            var socket = new Socket(point.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(point);
            socket.Listen(512);
            SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
            eventArgs.Completed += Completed;
            socket.AcceptAsync(eventArgs);
            return socket;
            // eventArgs.SetBuffer
        }
        public static void SignSSL(String hostName)
        {
            if (hostName.StartsWith("www.") == false && CheckSSL(hostName))
            {

                var secret = UMC.Data.WebResource.Instance().Provider["appSecret"];
                if (String.IsNullOrEmpty(secret) == false)
                {
                    HotCache.Put(new SiteCert
                    {
                        Domain = hostName,
                        ExpirationTime = 0,
                        CheckTime = Utility.TimeSpan()
                    });

                    CheckSSl(secret, hostName, true);
                }
            }
        }
        public static bool CheckSSL(String host)
        {
            var mainHost = UMC.Proxy.WebServlet.MainDomain;
            if (mainHost == host)
            {
                return true;
            }
            if (host.Length > mainHost.Length && host.EndsWith(mainHost))
            {
                var rook = host.Substring(0, host.Length - mainHost.Length - 1);
                var ls = rook.Split('.');
                if (ls.Length > 1)
                {

                    var siteConfig = UMC.Proxy.DataFactory.Instance().Site(ls[ls.Length - 1]);
                    if (siteConfig != null)
                    {
                        return ls[0] == "www";
                    }
                    return false;
                }
                else if (UMC.Proxy.DataFactory.Instance().Site(ls[0]) != null)
                {
                    return true;

                }
                else if (String.Equals(ls[0], Data.WebResource.Instance().Provider["auth"]))
                {
                    return true;
                }
            }

            return UMC.Proxy.DataFactory.Instance().Host(host) != null;
        }
        List<String> _urls = new List<string>();
        public const String UnixPath = @"/tmp/umc.unix";
        string Config(ProviderConfiguration hosts)
        {
            UMC.Proxy.WebServlet.IsHttps = UMC.Data.WebResource.Instance().Provider["scheme"] == "https";
            UMC.Proxy.WebServlet.MainDomain = UMC.Data.WebResource.Instance().Provider["domain"] ?? "localhost";
            _urls.Clear();
            var host = new Dictionary<int, Socket[]>();

            var sb = new StringBuilder();
            foreach (var p in hosts.Providers)
            {
                switch (p.Type)
                {
                    case "unix":
                        if (Socket.OSSupportsUnixDomainSockets)
                        {

                            if (_host.ContainsKey(0) == false)
                            {
                                if (System.IO.Directory.Exists(UnixPath))
                                {
                                    System.IO.Directory.Delete(UnixPath, true);
                                }
                                if (System.IO.File.Exists(UnixPath))
                                {
                                    System.IO.File.Delete(UnixPath);
                                }
                                try
                                {
                                    var unix = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
                                    unix.Bind(new UnixDomainSocketEndPoint(UnixPath));
                                    unix.Listen(512);
                                    SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
                                    eventArgs.Completed += Unix;
                                    unix.AcceptAsync(eventArgs);
                                    host[0] = new Socket[] { unix };

                                    _urls.Add("unix://" + UnixPath);
                                }
                                catch (Exception ex)
                                {
                                    sb.Append($"Unix:{UnixPath} {ex.Message};");

                                }
                            }
                            else
                            {
                                _urls.Add("unix://" + UnixPath);
                                host[0] = _host[0];
                                _host.Remove(0);
                            }
                        }
                        break;
                    case "https":
                        {
                            int port = Utility.IntParse(p.Attributes["port"], 443);

                            try
                            {
                                if (_host.ContainsKey(port) == false)
                                {
                                    if (host.ContainsKey(port) == false)
                                    {
                                        var list = new List<Socket>();
                                        if (Socket.OSSupportsIPv4)
                                        {
                                            list.Add(BindSocket(new IPEndPoint(IPAddress.Any, port), Https));
                                        }
                                        if (Socket.OSSupportsIPv6)
                                        {
                                            list.Add(BindSocket(new IPEndPoint(IPAddress.IPv6Any, port), Https));
                                        }
                                        host[port] = list.ToArray();
                                    }
                                }
                                else
                                {
                                    host[port] = _host[port];
                                    _host.Remove(port);
                                }

                                _urls.Add($"https://*:{port}");


                            }
                            catch (Exception ex)
                            {
                                sb.Append($"Port:{port} {ex.Message};");
                            }
                        }
                        break;
                    case "http":
                    default:
                        {
                            int port = Utility.IntParse(p.Attributes["port"], 80);

                            if (_host.ContainsKey(port) == false)
                            {
                                if (host.ContainsKey(port) == false)
                                {

                                    try
                                    {
                                        var list = new List<Socket>();
                                        if (Socket.OSSupportsIPv4)
                                        {
                                            list.Add(BindSocket(new IPEndPoint(IPAddress.Any, port), Http));
                                        }
                                        if (Socket.OSSupportsIPv6)
                                        {
                                            list.Add(BindSocket(new IPEndPoint(IPAddress.IPv6Any, port), Http));
                                        }
                                        host[port] = list.ToArray();

                                    }
                                    catch (Exception ex)
                                    {
                                        sb.Append($"Port:{port} {ex.Message};");
                                    }
                                }
                                _urls.Add($"http://*:{port}");
                            }
                            else
                            {

                                host[port] = _host[port];
                                _host.Remove(port);
                                _urls.Add($"http://*:{port}");
                            }


                        }
                        break;
                }
            }
            foreach (var s in this._host.Values)
            {
                foreach (var v in s)
                {
                    v.Close();
                    v.Close();
                }
            }
            this._host.Clear();
            this._host = host;

            StartMsg = sb.ToString();
            return sb.ToString();

        }
        static HttpMimeServier httpMimeServier;
        bool IsStop = false;

        ManualResetEvent mre = new ManualResetEvent(false);
        public static void Start()
        {
            httpMimeServier = new HttpMimeServier();


            var webr = UMC.Data.WebResource.Instance();
            if (String.Equals(webr.Provider["webvpn"], "false") == false && String.IsNullOrEmpty(webr.Provider["appSecret"]) == false)
            {
                httpMimeServier.Bridge();

            }

            Pipe();


            Register(3600, httpMimeServier);

            while (httpMimeServier.IsStop == false)
            {

                httpMimeServier.mre.WaitOne(10000);
                try
                {
                    CheckLink();
                    UMC.Net.NetProxy.Check();
                    var now = Utility.TimeSpan();

                    int count = DoWorkers.Count;
                    while (DoWorkers.TryDequeue(out var _top))
                    {
                        if (_top.Item1 < now)
                        {
                            _top.Item2.DoWork();
                        }
                        else
                        {
                            DoWorkers.Enqueue(_top);
                        }

                        count--;
                        if (count <= 0)
                        {
                            break;
                        }
                    }

                }
                catch (Exception ex)
                {
                    UMC.Data.Utility.Error("Server", DateTime.Now, ex.ToString());
                }

            }

            HotCache.Close();

            foreach (var s in httpMimeServier._host.Values)
            {
                foreach (var v in s)
                {
                    v.Close();
                    v.Close();
                }
            }
        }
        // int CheckCertTime = 0;

        public static string Load(ProviderConfiguration config)
        {
            return httpMimeServier.Config(config);
        }
        // List
        static ConcurrentQueue<Tuple<int, IDoWorker>> DoWorkers = new ConcurrentQueue<Tuple<int, IDoWorker>>();
        public static void Register(int intervalTime, IDoWorker worker)
        {

            DoWorkers.Enqueue(Tuple.Create(Utility.TimeSpan() + intervalTime, worker));
        }
        class Stoper : IDoWorker
        {
            public void DoWork()
            {
                var secret = UMC.Data.WebResource.Instance().Provider["appSecret"];

                var webr = new Uri(APIProxy.Uri, "Transfer").WebRequest();

                UMC.Proxy.Utility.Sign(webr, secret);
                webr.Get(webr =>
                {
                    webr.ReadAsString(json =>
                    {
                        var meta = JSON.Deserialize<WebMeta>(json);
                        HttpServier.LicenseUsersSession = Utility.IntParse(meta["LicenseUsersSession"], 1000);
                        Data.Caches.ICacheSet cacheSet = UMC.Data.HotCache.Cache<UMC.Data.Entities.Session>();
                        if (cacheSet.Count > HttpServier.LicenseUsersSession)
                        {
                            httpMimeServier.IsStop = true;
                            httpMimeServier.mre.Set();
                        }

                    }, r =>
                    {
                        httpMimeServier.IsStop = true;
                        httpMimeServier.mre.Set();

                    });
                });
            }
        }
        String StartMsg;
        private HttpMimeServier()
        {
            using (var rsa = System.Security.Cryptography.RSA.Create())
            {
                var req = new CertificateRequest("CN=apiumc", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                certificate = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(10));

            }
            sslServerAuthentication = new SslServerAuthenticationOptions()
            {
                ServerCertificateSelectionCallback = ServerCertificateSelectionCallback,
                CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
                EncryptionPolicy = EncryptionPolicy.RequireEncryption,
                ClientCertificateRequired = false
            };

            HotCache.LoadFile();


            UMC.Web.WebResource.Instance(new UMC.Proxy.WebResource(), UMC.Web.WebResource.Instance().Provider);

            var hosts = Reflection.Configuration("host");
            if (hosts.Count == 0)
            {
                var http = UMC.Data.Provider.Create("*", "http");
                http.Attributes["port"] = "80";
                hosts.Add(http);
                var ssl = UMC.Data.Provider.Create("ssl", "https");
                ssl.Attributes["port"] = "443";
                hosts.Add(ssl);
                Reflection.Configuration("host", hosts);
            }

            var logSb = new StringBuilder();
            logSb.Append(this.Config(hosts));
            var writer = new System.IO.StringWriter(logSb);
            UMC.Data.Sql.Initializer.Register(writer, new UMC.Data.Entities.Initializer(), new UMC.Proxy.Entities.Initializer());
            writer.Flush();
            this.StartMsg = logSb.ToString();
            UMC.Net.APIProxy.Subscribes(_Server);


            var certs = Reflection.Configuration("certs");
            foreach (var cert in certs.Providers)
            {
                try
                {
                    var x509 = X509Certificate2.CreateFromPem(cert["publicKey"], cert["privateKey"]);
                    Certificater.Certificates[cert.Name] = new Certificater { Name = cert.Name, Certificate = x509 };

                }
                catch
                {

                }
            }

        }
        private static void CheckSSl(string secret, string domain, bool isAuto)
        {
            UMC.Proxy.Utility.Sign(new Uri(APIProxy.Uri, "Certificater").WebRequest(), secret).Post(new WebMeta().Put("type", isAuto ? "auto" : "apply", "domain", domain), webr =>
            {
                if (webr.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    webr.ReadAsString(jsonStr =>
                   {
                       var hs = JSON.Deserialize<WebMeta>(jsonStr);
                       if (String.Equals(hs?["code"], "completed"))
                       {
                           UMC.Proxy.Utility.Sign(new Uri(APIProxy.Uri, "Certificater").WebRequest(), secret)
                                 .Post(new WebMeta().Put("type", "cert", "domain", domain), UMC.Proxy.Utility.Certificate);

                       }
                   });
                }
            });

        }


        private void Cert()
        {
            var secret = UMC.Data.WebResource.Instance().Provider["appSecret"];
            int nextIndex = 0;

            if (String.IsNullOrEmpty(secret) == false)
            {
                var now = Utility.TimeSpan(DateTime.Now.AddDays(5));
                while (nextIndex >= 0)
                {

                    var fs = HotCache.Find(new SiteCert(), false, 0, 500, out nextIndex);
                    foreach (var r in fs)
                    {
                        if ((r.IsApiumc ?? false) == false && String.IsNullOrEmpty(r.PrivateKey) == false && String.IsNullOrEmpty(r.PublicKey) == false)
                        {
                            if (r.ExpirationTime < now)
                            {
                                CheckSSl(secret, r.Domain, false);
                            }
                        }
                    };

                }
            }
        }
        private void Unix(object sender, SocketAsyncEventArgs eventArgs)
        {
            if (eventArgs.SocketError == SocketError.Success)
            {
                var client = eventArgs.AcceptSocket;
                if (client != null)
                {
                    eventArgs.AcceptSocket = null;

                    try
                    {
                        new HttpMimeSocket(client, "127.0.0.1");

                    }
                    catch
                    {
                        client.Close();
                        client.Dispose();
                    }
                    if (!((Socket)sender).AcceptAsync(eventArgs))
                    {
                        Unix(sender, eventArgs);
                    }

                }

            }
        }
        private void Http(object sender, SocketAsyncEventArgs eventArgs)
        {
            if (eventArgs.SocketError == SocketError.Success)
            {
                var client = eventArgs.AcceptSocket;
                if (client != null)
                {

                    try
                    {
                        var ip = (client.RemoteEndPoint as IPEndPoint).Address;

                        new HttpMimeSocket(client, ip.ToString());
                        eventArgs.AcceptSocket = null;

                    }
                    catch
                    {
                        client.Close();
                        client.Dispose();
                    }
                    if (!((Socket)sender).AcceptAsync(eventArgs))
                    {
                        Http(sender, eventArgs);
                    }
                }

            }
        }
        private async void Https(Socket client)
        {

            SslStream sslStream = new SslStream(new NetworkStream(client, true), false);
            try
            {
                await sslStream.AuthenticateAsServerAsync(this.sslServerAuthentication);
                var ip = client.RemoteEndPoint as IPEndPoint;
                new HttpsMimeSocket(sslStream, ip.Address.ToString());

            }
            catch
            {
                sslStream.Close();
                sslStream.Dispose();
                client.Close();
            }


        }
        private void Https(object sender, SocketAsyncEventArgs eventArgs)
        {
            if (eventArgs.SocketError == SocketError.Success)
            {
                var client = eventArgs.AcceptSocket;
                if (client != null)
                {
                    Https(client);
                }

                eventArgs.AcceptSocket = null;
                if (!((Socket)sender).AcceptAsync(eventArgs))
                {
                    Https(sender, eventArgs);
                }
            }
        }
        bool isBridging = false;
        void Bridge()
        {
            isBridging = true;

            var secret = UMC.Data.WebResource.Instance().Provider["appSecret"];

            var webr = new Uri(APIProxy.Uri, "Transfer").WebRequest();

            UMC.Proxy.Utility.Sign(webr, secret);
            webr.Get(webr =>
            {
                webr.ReadAsString(json =>
                {
                    isBridging = false;
                    var meta = JSON.Deserialize<WebMeta>(json);
                    HttpServier.LicenseUsersSession = Utility.IntParse(meta["LicenseUsersSession"], 1000);
                    if (meta.ContainsKey("domain") && meta.ContainsKey("ip"))
                    {
                        var ip = meta["ip"];
                        var port = UMC.Data.Utility.IntParse(meta["port"], 0);

                        HttpBridgeClient.Start(meta["domain"], ip, port, 4);
                    }

                }, e => isBridging = false);
            });


        }

        static async void Pipe()
        {
            using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("APIUMC", PipeDirection.InOut))
            {
                do
                {
                    await pipeServer.WaitForConnectionAsync();

                    var bufer = new byte[100];
                    int l = pipeServer.Read(bufer, 0, 100);

                    try
                    {
                        var str = System.Text.Encoding.UTF8.GetString(bufer, 0, l).Split(' ');
                        switch (str[0])
                        {
                            case "clear":
                                // UMC.Data.ProviderConfiguration.Cache.Clear();
                                pipeServer.Write(System.Text.Encoding.UTF8.GetBytes("配置缓存已经清空。\r\n"));
                                break;
                            case "vpn":
                                if (str.Length > 1)
                                {
                                    switch (str[1])
                                    {
                                        case "start":
                                            pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(HttpBridgeClient.ServerChange(2)));
                                            break;
                                        case "stop":
                                            pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(HttpBridgeClient.ServerChange(1)));
                                            break;
                                        default:
                                            pipeServer.Write(System.Text.Encoding.UTF8.GetBytes($"不支持“vpn {str[1]}”指令。\r\n"));
                                            break;
                                    }
                                }
                                else
                                {
                                    pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(HttpBridgeClient.ServerChange(0)));
                                }
                                break;
                            case "https":
                                {

                                    var hosts = Reflection.Configuration("host");
                                    if (str.Length > 1)
                                    {

                                        if (Utility.IntParse(str[1], 0) > 0)
                                        {
                                            var http = UMC.Data.Provider.Create("ssl", "https");
                                            http.Attributes["port"] = str[1];

                                            hosts.Add(http);

                                            Reflection.Configuration("host", hosts);

                                        }

                                    }
                                    else
                                    {
                                        if (hosts.ContainsKey("ssl") == false)
                                        {
                                            var http = UMC.Data.Provider.Create("ssl", "https");

                                            http.Attributes["port"] = "443";

                                            hosts.Add(http);

                                            Reflection.Configuration("host", hosts);

                                        }
                                    }
                                    httpMimeServier.Config(Reflection.Configuration("host"));
                                }
                                goto default;
                            case "ssl":
                                {
                                    if (str.Length > 1)
                                    {
                                        var host = str[1];

                                        if (System.Text.RegularExpressions.Regex.IsMatch(host, @"^([a-z0-9\*]([a-z0-9\-]{0,61}[a-z0-9])?\.)+[a-z0-9]{1,6}$") == false)
                                        {
                                            pipeServer.Write(System.Text.Encoding.UTF8.GetBytes($"域名格式不正确。\r\n"));
                                            break;
                                        }

                                        var secret = UMC.Data.WebResource.Instance().Provider["appSecret"];
                                        if (String.IsNullOrEmpty(secret))
                                        {
                                            pipeServer.Write(System.Text.Encoding.UTF8.GetBytes("\a主体未登记，请在云桌面中完成登记\r\n"));
                                            break;
                                        }
                                        var webr2 = new Uri(APIProxy.Uri, "Certificater").WebRequest();
                                        UMC.Proxy.Utility.Sign(webr2, secret);

                                        var webr = webr2.Post(new WebMeta().Put("type", "apply", "domain", host).Put("dcv", str.Length > 2 ? str[2] : null));

                                        var jsonStr = webr.ReadAsString();
                                        if (webr.StatusCode == System.Net.HttpStatusCode.OK)
                                        {
                                            var hs = JSON.Deserialize<WebMeta>(jsonStr);
                                            if (string.Equals(hs["code"], "success"))
                                            {
                                                pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(hs["msg"] ?? "\t\b正在签发证书,大约一分钟签发完成\r\n"));

                                            }
                                            else if (string.Equals(hs["code"], "completed"))
                                            {
                                                if (Certificater.Certificates.TryGetValue(host, out var _cert) == false || _cert.Certificate == null)
                                                {
                                                    webr2.Post(new WebMeta().Put("type", "cert", "domain", host), UMC.Proxy.Utility.Certificate);
                                                }
                                                pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(String.Format("{0}\r\n\r\n强烈建议：请在\b云桌面->应用设置->网关服务\f中管理证书\r\n", hs["msg"])));

                                            }
                                            else
                                            {
                                                pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(String.Format("{0}\r\n\r\n强烈建议：请在\b云桌面->应用设置->网关服务\f中管理证书\r\n", hs["msg"])));

                                            }

                                        }
                                        else
                                        {
                                            pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(webr.ReadAsString() ?? $"请确保域名“{host}”解释到服务器，并开放80端口\r\n"));
                                        }

                                    }
                                    else
                                    {

                                        var now = UMC.Data.Utility.TimeSpan();
                                        var ls = Certificater.Certificates.Values.OrderBy(r =>
                                        {
                                            if (r.Certificate != null)
                                            {
                                                r.Time = Utility.TimeSpan(Convert.ToDateTime(r.Certificate.GetExpirationDateString()));

                                            }
                                            return r.Time;
                                        });
                                        var sb = new StringBuilder();
                                        sb.AppendLine("  过期\t\t\t\t证书");
                                        foreach (var r in ls)
                                        {
                                            sb.AppendLine($"{UMC.Proxy.Utility.Expire(now, r.Time, "\a正在签发")}\t\t\t{r.Name}");
                                        }
                                        if (ls.Count() == 0)
                                        {
                                            sb.AppendLine("\t\t还未有证书");
                                        }
                                        else
                                        {
                                            sb.AppendLine();
                                            sb.AppendLine("强烈建议：请在\b云桌面->应用设置->网关服务\f中管理证书");
                                        }
                                        pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
                                    }

                                }
                                break;
                            case "check":
                                if (str.Length > 1)
                                {
                                    var key = UMC.Data.Utility.Parse36Encode(UMC.Data.Utility.IntParse(new Guid(UMC.Data.Utility.MD5(System.AppContext.BaseDirectory)))); ;

                                    if (String.Equals(key, str[1]) == false)
                                    {
                                        pipeServer.Write(System.Text.Encoding.UTF8.GetBytes($"主程序目录：{UMC.Data.Utility.MapPath("~")}"));
                                    }
                                }
                                break;
                            case "http":
                            case "start":
                                if (str.Length > 1)
                                {
                                    if (Utility.IntParse(str[1], 0) > 0)
                                    {
                                        var http = UMC.Data.Provider.Create("*", "http");
                                        http.Attributes["port"] = str[1];

                                        var hosts = Reflection.Configuration("host");
                                        hosts.Add(http);

                                        Reflection.Configuration("host", hosts);

                                    }
                                }
                                httpMimeServier.Config(Reflection.Configuration("host"));
                                goto default;
                            case "stop":
                                pipeServer.Write(System.Text.Encoding.UTF8.GetBytes("正在停止ITME服务。\r\n"));
                                httpMimeServier.IsStop = true;
                                httpMimeServier.mre.Set();
                                return;
                            default:
                            case "info":
                                {

                                    var secret = UMC.Data.WebResource.Instance().Provider["appSecret"];
                                    var sb = new StringBuilder();

                                    if (String.IsNullOrEmpty(httpMimeServier.StartMsg) == false)
                                    {
                                        sb.AppendLine(httpMimeServier.StartMsg);
                                        httpMimeServier.StartMsg = String.Empty;
                                    }
                                    if (httpMimeServier._urls.Count > 0)
                                    {
                                        sb.Append("监听地址：\b");
                                        sb.AppendJoin("\f, \b", httpMimeServier._urls);
                                        sb.AppendLine();

                                        if (String.IsNullOrEmpty(secret))
                                        {
                                            sb.AppendLine($"Web VPN ：\a主体未登记\f，登记后，才可开启");
                                        }
                                        else if (HttpBridgeClient.IsRunning)
                                        {
                                            var bridge = UMC.Data.WebResource.Instance().Provider["bridge"];
                                            sb.AppendLine($"Web VPN ：\b{bridge}");
                                        }
                                        else if (httpMimeServier.isBridging)
                                        {
                                            var bridge = UMC.Data.WebResource.Instance().Provider["bridge"];
                                            sb.AppendLine($"Web VPN ：{bridge}  \a[连接中]");
                                        }
                                        else
                                        {
                                            sb.AppendLine($"Web VPN ：请用[vpn start]指令来开启");
                                        }


                                    }
                                    else
                                    {
                                        sb.AppendLine("监听地址：\a监听失败");
                                    }
                                    sb.AppendLine();

                                    if (String.IsNullOrEmpty(secret) == false)
                                    {
                                        var webr = new Uri(APIProxy.Uri, "Transfer").WebRequest();
                                        UMC.Proxy.Utility.Sign(webr, secret);
                                        var xhr = webr.Get();
                                        if (xhr.StatusCode == HttpStatusCode.OK)
                                        {
                                            var meta = JSON.Deserialize<WebMeta>(xhr.ReadAsString()) ?? new WebMeta();
                                            var caption = meta["caption"];
                                            var license = meta["license"];
                                            HttpServier.LicenseUsersSession = Utility.IntParse(meta["LicenseUsersSession"], 1000);
                                            if (String.IsNullOrEmpty(caption))
                                            {
                                                sb.AppendLine($"注册主体：\a主体未登记\f，请用网址登录云桌面->应用设置->安全注册中完成登记");
                                            }
                                            else
                                            {
                                                if (HttpServier.LicenseUsersSession > 0)
                                                {
                                                    sb.AppendLine($"注册信息：\a{license}\f 授权于 {caption} (会话限制\r{HttpServier.LicenseUsersSession}\f条)");

                                                    Data.Caches.ICacheSet cacheSet = UMC.Data.HotCache.Cache<UMC.Data.Entities.Session>();
                                                    if (cacheSet.Count > HttpServier.LicenseUsersSession)
                                                    {
                                                        sb.AppendLine();
                                                        sb.AppendLine($"版本升级：当前版本已超过会话限制，\r一个小时\f后将终止ITME服务");
                                                        // pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
                                                        Register(3600, new Stoper());


                                                    }
                                                }
                                                else
                                                {
                                                    sb.AppendLine($"注册信息：\b{license}\f 授权于 \b{caption}");
                                                }
                                            }
                                        }
                                        else
                                        {
                                            sb.AppendLine($"接口异常：\a{xhr.ReadAsString()}");

                                        }
                                    }
                                    else
                                    {
                                        sb.AppendLine($"注册主体：\a主体未登记\f，请在云桌面->应用设置->安全注册中完成登记");

                                    }


                                    pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
                                }
                                break;
                            case "pool":
                                pipeServer.Write(System.Text.Encoding.UTF8.GetBytes(Pool()));
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Utility.Error("App", ex);
                    }
                    finally
                    {

                        pipeServer.Disconnect();
                    }

                } while (true);

            }
        }

        static String Pool()
        {
            var _pool = Net.NetProxy.Pool;
            var sb = new StringBuilder();
            sb.AppendLine("Http Pools:");
            lock (_pool)
            {
                if (_pool.Count == 0)
                {
                    sb.AppendLine("\t\tEmpty");
                }
                else
                {
                    var p = _pool.GetEnumerator();

                    while (p.MoveNext())
                    {
                        sb.AppendFormat("{0}\t\t{2}\t\t{1}", p.Current.Value.Unwanted.Count, p.Current.Key, p.Current.Value.BurstError);
                        sb.AppendLine();
                    }
                }
            }
            return sb.ToString();
        }
        static void CheckLink()
        {
            var time = UMC.Data.Utility.TimeSpan();
            var ms = httpMimes.Values.ToArray();

            foreach (var b in ms)
            {
                try
                {

                    if ((b.ActiveTime + b.TimeOut) < time)
                    {
                        httpMimes.TryRemove(b.Id, out var link);
                        if (b.TimeOut > 30)
                        {
                            b.OutText(504, "Gateway Timeout");
                        }
                        else
                        {
                            b.Dispose();
                        }
                    }
                }
                catch
                {

                }
            }
            var ws = Host.HttpWebSocket.WebSockets.ToArray();
            foreach (var w in ws)
            {
                try
                {
                    if (w.ActiveTime + 60 < time)
                    {
                        w.Ping();

                    }
                }
                catch
                {

                }
            }

        }

        void IDoWorker.DoWork()
        {
            this.Cert();
            Register(3600, this);
        }


        internal static ConcurrentDictionary<int, HttpMime> httpMimes = new ConcurrentDictionary<int, HttpMime>();


    }



}
